enum CONN_STATU
{
    CLOSED,             //关闭状态,不再进行任何操作，释放资源
    CONNECTING,         //连接待处理，还需要进行各项设置才能开始监听通信
    CONNECTED,          //连接建立，可以通信
    CLOSING             //连接带关闭，尽快处理缓冲区剩余数据
};

class Connection;
using PtrConnection = std::shared_ptr<Connection>;

class Connection :public std::enable_shared_from_this<Connection>
{
private:
    uint64_t _id;       //连接的id，也是连接对应的超时任务的id
    int _sockfd;        //保存对应的描述符
    EventLoop* _loop;   //绑定的EventLoop
    CONN_STATU _con_statu;  //连接状态
    Socket _socket;     //套接字操作模块
    Channel _channel;   //事件管理模块
    Buffer _in_buffer;  //输入缓冲区
    Buffer _out_buffer; //输出缓冲区
    Any _context;       //连接上下文
    bool _enable_inactive_release;    //标识是否开启非活跃连接超时释放机制

    using EventCallBack = std::function<void(const PtrConnection&)>;        //用户设置的任意事件回调
    using ConnectCallBack = std::function<void(const PtrConnection&)>;    //用户设置的连接建立回调
    using MessageCallBack = std::function<void(const PtrConnection&,Buffer*)>;    //用户设置的新数据回调，需要传递输入缓冲区  
    using CloseCallBack = std::function<void(const PtrConnection&)>;        //用户设置的连接关闭回调
    using SvrCloseCallBack = std::function<void(const PtrConnection&)>;        //TcpServer设置的连接关闭回调
    ConnectCallBack _connect_cb;
    MessageCallBack _message_cb;
    CloseCallBack _close_cb;
    EventCallBack _event_cb;
    SvrCloseCallBack _svr_close_cb;
private:

    void ReleaseinLoop()        //实际关闭连接
    {
        assert(_con_statu == CLOSING);
        _con_statu = CLOSED;    //更新状态
        if(_loop->HasTimerTask(_id)) _loop->CancelTimerTask(_id);   //取消定时任务
        _channel.Remove();      //移除事件监控
        _socket.Close();        //关闭套接字
        if(_close_cb)   _close_cb(shared_from_this());        //先调用用户设置的关闭连接调用
        if(_svr_close_cb) _svr_close_cb(shared_from_this()); //再调用TcpServer提供的接口用于移除管理，删除基础计数
        //注意调用的顺序，因为Release接口并不需要保留一个shared_ptr参数，那么就意味着，可能调用完 _svr_close_cb之后，计数就为0，把资源释放了，那么这时候已经无法找到_close_cb了
    }
    void ShutDownInLoop()
    {
        _con_statu = CLOSING;   //设置连接待关闭
        if(_in_buffer.ReadSize()) //有数据待处理
            if(_message_cb) _message_cb(shared_from_this(),&_in_buffer);
        //所有数据都处理完之后，处理待发送数据
        if(_out_buffer.ReadSize())  //如果有数据待发送
        {
            _channel.EnableWrite();    //启动写事件监听
            //触发写事件之后，在写事件回调中会调用Release进行连接释放
        }
        else Release(); //如果没有数据待发送就直接关闭
    }

    void HandlerRead() //读事件回调
    {
        // 1 从套接字读取数据
#define READ_SIZE 65535
        char buffer[READ_SIZE] = {0};
        int ret = _socket.Read(buffer,READ_SIZE-1);
        if(ret < 0 )  //对Socket的Read做处理，只有真正出错的时候才返回 -1 ，其他的时候都返回 >= 0 的值
        {
            //说明套接字出错，那么此时也不能直接关闭连接，因为输出缓冲区中还有数据待发送，所以是调用ShutDown接口
            ShutDown();     //先处理剩余数据，再实际关闭连接
        }
        // 2 放入输入缓冲区
        _in_buffer.WriteAndPush(buffer,ret);
        // 3 调用新数据回调 
        if(_in_buffer.ReadSize())  //可能没读到数据，被信号打断了或者其他原因
        {
            if(_message_cb) _message_cb(shared_from_this(),&_in_buffer);   //shared_from_this() 会从当前对象的第一个创建的shared_ptr中进行拷贝
        }
        // if(_out_buffer.ReadSize()) _channel.EnableWrite(); //如果写入了新的数据，那么开启写事件监控      //这行代码放在Send接口中更合适
    }
    void HandlerWrite() //写事件回调
    {
        // 1 向套接字写入数据
        int ret =_socket.Send(_out_buffer.ReadPosition(),_out_buffer.ReadSize());  //直接尝试全部写完
        // 2 判断是否写完
        if(ret < 0)  //在 Socket 的Send接口中做处理，只有真正出错时才返回 -1 ，那么这时候不需要再继续任何处理数据的操作了，直接关闭连接
        {
            Release();  // 这个接口是实际关闭连接的接口
        }
        if(ret == _out_buffer.ReadSize()) //说明写完了,那么可以关闭写事件的监控了
        {
            _channel.DisableWwrite();   //关闭写事件监控，直到下一次
        }
        //否则就表示没写完，那么就先不管比写事件监控
        _out_buffer.MoveWriteOffset(ret); //不管怎么样都要移动读偏移
        //然后判断连接是否是待关闭状态，如果是，写完这次数据我们就必须要关闭连接了
        if(_con_statu == CLOSING) Release();
    }
    void HandlerClose() //挂断事件回调
    {
        if(_in_buffer.ReadSize())
        _message_cb(shared_from_this(),&_in_buffer);
        Release();
    }
    void HandlerError() //错误事件回调
    {
        HandlerClose();
    }
    void HandlerEvent() //任意事件回调
    {
        if(_enable_inactive_release)  //如果启动了非活跃超时释放
        _loop->RefreshTimerTask(_id);
        if(_event_cb) _event_cb(shared_from_this());
    }
    void EnableInactiveReleaseInLoop(uint64_t delay = 30)  //启动非活跃连接销毁
    {
        _enable_inactive_release = true;
        //判断是否已经有超时任务
        if(_loop->HasTimerTask(_id))   //说明这个连接有定时任务在时间轮，那么直接刷新延迟、
        {
            _loop->RefreshTimerTask(_id); //直接刷新,前面的时间轮的刷新策略需要更新，再刷新的时候需要启动任务，也就是 _is_cancled = true
        }
        else    //没有定时任务，那么需要添加
        {
            _loop->AddTimerTask(_id,delay,std::bind(&Connection::Release,this));  //把销毁任务添加进去
        }
    }
    void DisableInactuveReleaseInLoop()   //取消非活跃连接销毁
    {
        _enable_inactive_release = false;
        //判断时间轮中是否有该任务，如果有，那么需要取消
        if(_loop->HasTimerTask(_id))
        _loop->CancelTimerTask(_id);
    }
    void EstablishedInLoop()
    {
        if(_con_statu!=CONNECTING) abort(); //出错，因为这个函数调用时一定是处于连接待处理阶段的，不可能是其他的状态
        _con_statu = CONNECTED;  //更新状态
        _channel.EnableRead();  //启动读事件监听
        if(_connect_cb) _connect_cb(shared_from_this()); //调用用户设置的连接建立回调
    }
    void SendInLoop(const char* in , size_t len)       //发送数据(用户层面)
    {
       _out_buffer.WriteAndPush(in,len);
       //启动写事件监控
       if(_out_buffer.ReadSize()) _channel.EnableWrite(); 
    }
    void UpgradeInLoop(const Any& context,const ConnectCallBack& con , const MessageCallBack& msg, const CloseCallBack& clo,const EventCallBack& evt)
    {
        _context = context;
        _connect_cb = con;
        _message_cb = msg;
        _event_cb = evt;
        _close_cb = clo;
    }
public: //功能接口
    Connection(uint64_t id , int sockfd ,EventLoop* loop)
    :_id(id),_sockfd(sockfd),_loop(loop),_con_statu(CONNECTING),_socket(sockfd),_channel(_sockfd,_loop),_enable_inactive_release(false)
    {
        _channel.SetReadCallBack(std::bind(&Connection::HandlerRead,this));
        _channel.SetWriteCallBack(std::bind(&Connection::HandlerWrite,this));
        _channel.SetCloseCallBack(std::bind(&Connection::HandlerClose,this));
        _channel.SetErrorCallBack(std::bind(&Connection::HandlerError,this));
        _channel.SetEventCallBack(std::bind(&Connection::HandlerEvent,this));
    }
    void SetMessageCallBack(const MessageCallBack& cb){_message_cb = cb;}
    void SetConnectCallBack(const ConnectCallBack& cb){_connect_cb = cb;}
    void SetCloseCallBack(const CloseCallBack& cb){_close_cb = cb;}
    void SetEventCallBack(const EventCallBack& cb){_event_cb = cb;}
    void SetSvrCloseCallBack(const SvrCloseCallBack& cb){_svr_close_cb = cb;}
    void EnableInactiveRelease(uint64_t delay)  //启动非活跃连接销毁
    {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop,this,delay));
    }
    void DisableInactuveRelease()   //取消非活跃连接销毁
    {
        _loop->RunInLoop(std::bind(&Connection::DisableInactuveReleaseInLoop,this));
    }
    void SetContext(const Any& context){_context = context;} //设置上下文
    Any* GetContext() {return &_context;}
    void Established()
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop,this));
    }
    void Send(const char* in,size_t len)
    {
        _loop->RunInLoop(std::bind(&Connection::SendInLoop,this,in,len));
    }
    void Upgrade(const Any& context,const ConnectCallBack& con , const MessageCallBack& msg, const CloseCallBack& clo,const EventCallBack& evt)
    {
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop,this,context,con,msg,clo,evt));
    }
    void ShutDown()
    {
        _loop->RunInLoop(std::bind(&Connection::ShutDownInLoop,this));
    }  
    void Release()  //不提供给外部
    {
        _loop->RunInLoop(std::bind(&Connection::ReleaseinLoop,this));
    }
    int Fd()const {return _sockfd;}
    uint64_t Id()const {return _id;}
    ~Connection(){}
};